package com.whfc.influx.dao.impl;

import com.whfc.fse.constant.CraneMeasurement;
import com.whfc.fse.dto.FseCraneDataLogDTO;
import com.whfc.fse.entity.FseDeviceCraneDataLog;
import com.whfc.influx.dao.FseCraneDataLogDao;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.impl.InfluxDBMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.*;

/**
 * @Description:
 * @author: xugcheng
 * @version: 1.0
 * @date: 2021-07-13 15:30
 */
@Repository
public class FseCraneDataLogDaoImpl implements FseCraneDataLogDao {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 数据库名称
     */
    private static final String database = CraneMeasurement.DATABASE;

    /**
     * 表名
     */
    private static final String measurement = CraneMeasurement.MEASUREMENT;

    /**
     * 保留策略
     */
    private static final String retentionPolicy = CraneMeasurement.RETENTION_POLICY;

    /**
     * 时间单位:秒
     */
    private static final TimeUnit timeUnit = TimeUnit.SECONDS;

    @Autowired
    private InfluxDB influxDB;

    @Autowired
    private InfluxDBMapper influxDBMapper;

    @Override
    public void insert(FseDeviceCraneDataLog record) {
        logger.info("influxdb的insert方法");
        influxDB.setDatabase(database);
        influxDB.setRetentionPolicy(retentionPolicy);
        influxDB.write(this.buildDataPoint(record));

    }

    @Override
    public void batchInsert(List<FseDeviceCraneDataLog> logList) {
        logger.info("influxdb的batchInsert方法");
        BatchPoints.Builder batchBuiler = BatchPoints.builder();
        for (FseDeviceCraneDataLog record : logList) {
            Point point = this.buildDataPoint(record);
            batchBuiler.point(point);
        }
        influxDB.setDatabase(database);
        influxDB.setRetentionPolicy(retentionPolicy);
        influxDB.write(batchBuiler.build());
    }

    @Override
    public List<FseCraneDataLogDTO> selectByCraneIdAndTime(Integer craneId, Date startTime, Date endTime) {
        logger.info("influxdb的selectByCraneIdAndTime方法");
        Query query = select().from(database, measurement)
                .where(eq("craneId", String.valueOf(craneId)))
                .andNested()
                .and(gte("time", startTime.toInstant().toString()))
                .and(lte("time", endTime.toInstant().toString()))
                .close()
                .orderBy(asc());
        logger.info(query.getCommand());
        List<FseCraneDataLogDTO> list = influxDBMapper.query(query, FseCraneDataLogDTO.class);
        this.transformTime(list);
        return list;
    }

    /**
     * 构建数据点
     *
     * @param record
     * @return
     */
    private Point buildDataPoint(FseDeviceCraneDataLog record) {
        logger.debug("influxdb的buildDataPoint方法");
        Point.Builder builder = Point
                .measurement(measurement)
                .time(record.getTime().toInstant().getEpochSecond(), timeUnit);
        if (!ObjectUtils.isEmpty(record.getCraneId())) {
            builder.tag("craneId", String.valueOf(record.getCraneId()));
        }
        if (!ObjectUtils.isEmpty(record.getRange())) {
            builder.addField("range", record.getRange());
        }
        if (!ObjectUtils.isEmpty(record.getMomentRatio())) {
            builder.addField("momentRatio", record.getMomentRatio());
        }
        if (!ObjectUtils.isEmpty(record.getHeight())) {
            builder.addField("height", record.getHeight());
        }
        if (!ObjectUtils.isEmpty(record.getWeight())) {
            builder.addField("weight", record.getWeight());
        }
        if (!ObjectUtils.isEmpty(record.getWindSpeed())) {
            builder.addField("windSpeed", record.getWindSpeed());
        }
        if (!ObjectUtils.isEmpty(record.getDipAngle())) {
            builder.addField("dipAngle", record.getDipAngle());
        }
        if (!ObjectUtils.isEmpty(record.getTurnAngle())) {
            builder.addField("turnAngle", record.getTurnAngle());
        }
        if (!ObjectUtils.isEmpty(record.getDelFlag())) {
            builder.addField("delFlag", record.getDelFlag());
        }
        builder.addField("serverTime", System.currentTimeMillis() / 1000);
        return builder.build();
    }

    /**
     * 时间类型转换
     *
     * @param list
     */
    private void transformTime(List<FseCraneDataLogDTO> list) {
        for (FseCraneDataLogDTO dto : list) {
            dto.setTime(Date.from(dto.getDeviceTime()));
            if (!ObjectUtils.isEmpty(dto.getServerTime())) {
                dto.setCreateTime(new Date(dto.getServerTime() * 1000));
            }
        }
    }
}
